'''
OpenMV搭配ATWINC1500 WiFi模块，实现图传+面部追踪的例程

程序本身是OpenMV原作者的编写，我只修改了一些细节，如画面参数、连接提示、图像显示帧速等
还加入了面部追踪程序
模块需要连接至无线路由（热点），只支持2.4Ghz。另有OpenMV作为热点的程序，但会使链接他的设备无法连接互联网，所以不推荐。
图传程序支持任何可以联网且有HTTP浏览器的设备，包括电脑、手机、平板等。

图传程序可以融入任何你自己的程序中，比如我B站的智能小车，就是基于OpenMV4和WiFi模块，但要注意：
当接收图像的浏览器关闭或断开后，OpenMV端的图传程序也会终止，进入等待连接模式
不合理的安排，会导致你的程序卡在等待连接处
注意程序执行时序！

由于OpenMV没有websocket库，无法实现ESP32那样的网页图传+网页按钮遥控
需要在底层加入相关支持库，或上位机有通讯程序，通过TCP/UDP透传

bilibili@程欢欢的智能控制集
20230826
'''
# MJPEG Streaming
#
# This example shows off how to do MJPEG streaming to a FIREFOX webrowser
# Chrome, Firefox and MJpegViewer App on Android have been tested.
# Connect to the IP address/port printed out from ifconfig to view the stream.

import sensor, image, time, network, usocket, sys

# 需要配置的无线网络信息
SSID ='LL-Love'
KEY  ='06150407'

HOST =''     # 使用第一个可用的网络接口
PORT = 8080  # 使用一个非特权端口

# 重置图像传感器
sensor.reset()
sensor.set_framesize(sensor.QVGA)
sensor.set_pixformat(sensor.RGB565)

# 初始化无线网络模块并连接到指定网络
print("正在尝试连接...（可能需要一点时间）...")
wlan = network.WINC()
wlan.connect(SSID, key=KEY, security=wlan.WPA_PSK)

# 打印一些有关无线网络的信息，以便在浏览器中访问
wlan_inf = wlan.ifconfig()
print('本机IP：' + wlan_inf[0])
print('子网掩码：' + wlan_inf[1])
print('路由IP：' + wlan_inf[3])
print('查看图传画面，浏览器输入网址：' + wlan_inf[0] + ':8080')

# 创建服务器套接字
s = usocket.socket(usocket.AF_INET, usocket.SOCK_STREAM)

# 绑定并监听
s.bind([HOST, PORT])
s.listen(5)

# 将服务器套接字设置为阻塞模式
s.setblocking(True)

# 分配一个较小的图像缓冲区，用于人脸检测
img_small = sensor.alloc_extra_fb(160,120,sensor.GRAYSCALE)
face_cascade = image.HaarCascade("frontalface", stages=20)

def start_streaming(s):
    print ('等待连接...')
    client, addr = s.accept()
    # 设置客户端套接字的超时时间为2秒
    client.settimeout(2.0)
    print ('已连接到 ' + addr[0] + ':' + str(addr[1]))

    # 从客户端读取请求
    data = client.recv(1024)
    # 此处可以解析客户端的请求

    # 发送多部分响应头
    client.send("HTTP/1.1 200 OK\r\n" \
                "Server: OpenMV\r\n" \
                "Content-Type: multipart/x-mixed-replace;boundary=openmv\r\n" \
                "Cache-Control: no-cache\r\n" \
                "Pragma: no-cache\r\n\r\n")

    # FPS计时
    clock = time.clock()

    # 开始发送图像
    fps = 0
    while (True):
        clock.tick()
        frame = sensor.snapshot()

        # 创建一个较小的灰度图像，用于人脸检测
        img_small.draw_image(frame, 0, 0, x_size=160, y_size=120)
        objects = img_small.find_features(face_cascade, threshold=0.65, scale_factor=1.5)

        # 在原始图像上绘制人脸框
        for r in objects:
            scaled_rect = [v * 2 for v in r]
            frame.draw_rectangle(scaled_rect)

        # 在图像上显示FPS
        frame.draw_string(10,10,'FPS:'+str(round(fps)), scale=2, color=(255,0,0))

        # 压缩图像并发送
        cframe = frame.compressed(quality=50)
        header = "\r\n--openmv\r\n" \
                 "Content-Type: image/jpeg\r\n"\
                 "Content-Length:"+str(cframe.size())+"\r\n\r\n"
        client.send(header)
        client.send(cframe)

        fps = clock.fps()
        print(fps)

while (True):
    try:
        start_streaming(s)
    except OSError as e:
        print("套接字错误: ", e)

